#include <omp.h>
#include <queue>
#include <cstdlib>

#include "Defines.h"

using namespace std;

/*
 * =====================================================================================
 *        Class:  buffer
 *  Description:  Classe que representa um buffer thread-safe
 * =====================================================================================
 */
template<class T> class buffer
{

public:

    /*-----------------------------------------------------------------------------
     *  Contrói um novo buffer circular vazio passando o tamanho do buffer
     *-----------------------------------------------------------------------------*/
    buffer(uint size);

    /*-----------------------------------------------------------------------------
     *  Destrói o buffer
     *-----------------------------------------------------------------------------*/
    virtual ~buffer();

    /*-----------------------------------------------------------------------------
     *  Insere um valor no buffer passando a iteração corrente
     *-----------------------------------------------------------------------------*/
    void put(T& t, uint i);

    /*-----------------------------------------------------------------------------
     *  Retorna o valor do buffer passando a iteração corrente
     *-----------------------------------------------------------------------------*/
    T& get(uint i);

private:

    /*-----------------------------------------------------------------------------
     *  Vetor utilizado para armazenar os dados do buffer
     *-----------------------------------------------------------------------------*/
    T* vec;

    /*-----------------------------------------------------------------------------
     *  Tamanho do buffer
     *-----------------------------------------------------------------------------*/
    uint size;

};

/*
 *--------------------------------------------------------------------------------------
 *       Class:  buffer
 *      Method:  buffer
 * Description:  Contrói um novo buffer circular passando o tamanho do buffer
 *--------------------------------------------------------------------------------------
 */
template<class T> buffer<T>::buffer(uint size)
{
    this->size = size;
    vec = new T[size];
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  buffer
 *      Method:  ~buffer
 * Description:  Destrói o buffer
 *--------------------------------------------------------------------------------------
 */
template<class T> buffer<T>::~buffer()
{
    delete[] vec;
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  buffer
 *      Method:  put
 * Description:  Insere um valor no buffer passando a iteração corrente
 *--------------------------------------------------------------------------------------
 */
template<class T> void buffer<T>::put(T& t, uint i)
{
    vec[i % size] = t;
}

/*
 *--------------------------------------------------------------------------------------
 *       Class:  buffer
 *      Method:  get
 * Description:  Retorna o valor do buffer passando a iteração corrente 
 *--------------------------------------------------------------------------------------
 */
template<class T> T& buffer<T>::get(uint i)
{
    return vec[i % size];
}

